﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using UvsChess;
using StudentAI;
using StudentAI.BitBoard;

namespace StudentAI.tests
{
    [TestFixture]
    public class TestMovement
    {

        [Test]
        public void TestKnight()
        {
            HashSet<ChessLocation> validMoves = new HashSet<ChessLocation>();
            ChessBoard board = new ChessBoard("r1bqkbnr/ppp1pppp/3p4/1n6/4N3/2P5/PP1PPPPP/RNBQKB1R w KQkq - 0 1");

            validMoves.Add(new ChessLocation(3, 4));
            validMoves.Add(new ChessLocation(2, 5));
            validMoves.Add(new ChessLocation(0, 5));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(1, 3))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(2, 3));
            validMoves.Add(new ChessLocation(3, 2));
            validMoves.Add(new ChessLocation(5, 2));
            validMoves.Add(new ChessLocation(6, 3));
            validMoves.Add(new ChessLocation(6, 5));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(4, 4))));

        }

        [Test]
        public void TestBishop()
        {
            HashSet<ChessLocation> validMoves = new HashSet<ChessLocation>();
            ChessBoard board = new ChessBoard("rnbqk1nr/pp2bppp/3p4/2p5/3Bp3/7B/PPPPPPPP/RN1QK1NR w KQkq - 0 1");

            validMoves.Add(new ChessLocation(3, 1));
            validMoves.Add(new ChessLocation(4, 2));
            validMoves.Add(new ChessLocation(5, 3));
            validMoves.Add(new ChessLocation(6, 4));
            validMoves.Add(new ChessLocation(7, 5));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(2, 0))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(5, 0));
            validMoves.Add(new ChessLocation(5, 2));
            validMoves.Add(new ChessLocation(6, 3));
            validMoves.Add(new ChessLocation(7, 4));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(4, 1))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(4, 3));
            validMoves.Add(new ChessLocation(5, 2));
            validMoves.Add(new ChessLocation(6, 1));
            validMoves.Add(new ChessLocation(2, 3));
            validMoves.Add(new ChessLocation(2, 5));
            validMoves.Add(new ChessLocation(4, 5));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(3, 4))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(6, 4));
            validMoves.Add(new ChessLocation(5, 3));
            validMoves.Add(new ChessLocation(4, 2));
            validMoves.Add(new ChessLocation(3, 1));
            validMoves.Add(new ChessLocation(2, 0));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(7, 5))));
        }

        [Test]
        public void TestRook()
        {
            HashSet<ChessLocation> validMoves = new HashSet<ChessLocation>();
            ChessBoard board = new ChessBoard("1n1qkbnr/6pp/2b2R2/8/2N1r3/8/PPPPPPPP/2BQKBNR w KQkq - 0 1");

            validMoves.Add(new ChessLocation(2, 2));
            validMoves.Add(new ChessLocation(3, 2));
            validMoves.Add(new ChessLocation(4, 2));
            validMoves.Add(new ChessLocation(5, 1));
            validMoves.Add(new ChessLocation(5, 0));
            validMoves.Add(new ChessLocation(6, 2));
            validMoves.Add(new ChessLocation(7, 2));
            validMoves.Add(new ChessLocation(5, 3));
            validMoves.Add(new ChessLocation(5, 4));
            validMoves.Add(new ChessLocation(5, 5));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(5, 2))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(2, 4));
            validMoves.Add(new ChessLocation(3, 4));
            validMoves.Add(new ChessLocation(4, 3));
            validMoves.Add(new ChessLocation(4, 2));
            validMoves.Add(new ChessLocation(4, 1));
            validMoves.Add(new ChessLocation(5, 4));
            validMoves.Add(new ChessLocation(6, 4));
            validMoves.Add(new ChessLocation(7, 4));
            validMoves.Add(new ChessLocation(4, 5));
            validMoves.Add(new ChessLocation(4, 6));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(4, 4))));
        }

        [Test]
        public void TestQueen()
        {
            HashSet<ChessLocation> validMoves = new HashSet<ChessLocation>();
            ChessBoard board = new ChessBoard("rnbqkbnr/pppppppp/8/8/4Q3/8/PPPPPPPP/RNB1KBNR w KQkq - 0 1");

            validMoves.Add(new ChessLocation(3, 5));
            validMoves.Add(new ChessLocation(5, 5));
            validMoves.Add(new ChessLocation(4, 5));
            validMoves.Add(new ChessLocation(0, 4));
            validMoves.Add(new ChessLocation(1, 4));
            validMoves.Add(new ChessLocation(2, 4));
            validMoves.Add(new ChessLocation(3, 4));
            validMoves.Add(new ChessLocation(5, 4));
            validMoves.Add(new ChessLocation(6, 4));
            validMoves.Add(new ChessLocation(7, 4));
            validMoves.Add(new ChessLocation(3, 3));
            validMoves.Add(new ChessLocation(4, 3));
            validMoves.Add(new ChessLocation(5, 3));
            validMoves.Add(new ChessLocation(2, 2));
            validMoves.Add(new ChessLocation(4, 2));
            validMoves.Add(new ChessLocation(6, 2));
            validMoves.Add(new ChessLocation(1, 1));
            validMoves.Add(new ChessLocation(4, 1));
            validMoves.Add(new ChessLocation(7, 1));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(4, 4))));
        }

        [Test]
        public void TestKing()
        {
            HashSet<ChessLocation> validMoves = new HashSet<ChessLocation>();
            ChessBoard board = new ChessBoard("r1bq1bnr/pppppppp/8/7k/Q7/1Bn4B/2K1PPPP/6NR w KQkq - 0 1");

            validMoves.Add(new ChessLocation(2, 5));
            validMoves.Add(new ChessLocation(3, 5));
            validMoves.Add(new ChessLocation(3, 6));
            validMoves.Add(new ChessLocation(2, 7));
            validMoves.Add(new ChessLocation(1, 6));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(2, 6))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(6, 3));
            validMoves.Add(new ChessLocation(6, 2));
            validMoves.Add(new ChessLocation(7, 2));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(7, 3))));
        }

        [Test]
        public void TestPawn()
        {
            HashSet<ChessLocation> validMoves = new HashSet<ChessLocation>();
            ChessBoard board = new ChessBoard("rnbqkbnr/p1p2ppp/3p4/1p2p3/1P3P2/6P1/P1PPP2P/RNBQKBNR w KQkq - 0 1");

            validMoves.Add(new ChessLocation(7, 5));
            validMoves.Add(new ChessLocation(7, 4));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(7, 6))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(6, 4));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(6, 5))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(4, 3));
            validMoves.Add(new ChessLocation(5, 3));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(5, 4))));

            validMoves.Clear();
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.White, new ChessLocation(1, 4))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(5, 4));
            validMoves.Add(new ChessLocation(4, 4));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(4, 3))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(3, 3));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(3, 2))));

            validMoves.Clear();
            validMoves.Add(new ChessLocation(2, 2));
            validMoves.Add(new ChessLocation(2, 3));
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(2, 1))));

            validMoves.Clear();
            Assert.IsTrue(validMoves.SetEquals(Movement.getFilteredPieceMoves(board, ChessColor.Black, new ChessLocation(1, 3))));

        }

        /*
        [Test]
        public void TestZobrist()
        {
            Board.initZobrist(); //creates random number for zobrist hash
            Console.WriteLine("Test basic movement");
            ChessBoard board = new ChessBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 0");
            Board b = new Board(board, ChessColor.White);
            Console.WriteLine(b.Fen(true));
            Console.WriteLine(b.getZobrist());

            //Move 1: 
            byte loc1 = 62; //g1
            byte loc2 = 8*5+5; //f3 
            b.MovePiece(loc1, loc2, ChessPieceType.Queen);
            Console.WriteLine(b.Fen(true));
            Console.WriteLine(b.getZobrist());

            ChessBoard board2 = new ChessBoard("rnbqkbnr/pppppppp/8/8/8/5N2/PPPPPPPP/RNBQKB1R b KQk - 0 0");
            Board b2 = new Board(board2, ChessColor.Black);
            Console.WriteLine(b2.Fen(true));
            Console.WriteLine(b2.getZobrist());
            Assert.IsTrue(b.Fen(true).Equals(b2.Fen(true)));
            Assert.IsTrue(b.getZobrist()==b2.getZobrist());

            Console.WriteLine("Testing pawn promotion");
            ChessBoard board3 = new ChessBoard("1nbqkbnr/Pppppppp/8/8/8/8/1PPPPPPP/RNBQKBNR w KQkq - 0 0");
            Board b3 = new Board(board3, ChessColor.White);
            Console.WriteLine(b3.Fen(true));
            Console.WriteLine(b3.getZobrist());

            b3.MovePiece(8, 0, ChessPieceType.Queen); //a7 to a8
            Console.WriteLine(b3.Fen(true));
            Console.WriteLine(b3.getZobrist());


            ChessBoard board4 = new ChessBoard("Qnbqkbnr/1ppppppp/8/8/8/8/1PPPPPPP/RNBQKBNR b KQk - 0 0");
            Board b4 = new Board(board4, ChessColor.Black);
            Console.WriteLine(b4.Fen(true));
            Console.WriteLine(b4.getZobrist());
            Assert.IsTrue(b3.getZobrist() == b4.getZobrist());


            Console.WriteLine("Testing capture");
            ChessBoard board5 = new ChessBoard("rnbqkbnr/pppppppp/1N6/8/8/8/PPPPPPPP/RNBQKB1R w KQkq - 0 0");
            Board b5 = new Board(board5, ChessColor.White);
            Console.WriteLine(b5.Fen(true));
            Console.WriteLine(b5.getZobrist());

            b5.MovePiece(17, 0, ChessPieceType.Queen); //b6 to a8
            Console.WriteLine(b5.Fen(true));
            Console.WriteLine(b5.getZobrist());


            ChessBoard board6 = new ChessBoard("Nnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKB1R w KQk - 0 0");
            Board b6 = new Board(board6, ChessColor.Black);
            Console.WriteLine(b6.Fen(true));
            Console.WriteLine(b6.getZobrist());
            Assert.IsTrue(b5.getZobrist() == b6.getZobrist());

        }
         * */

    }
}
